extends Node2D

# 预加载蝙蝠场景
const BAT_SCENE = preload("uid://da8cu5y0qt54p")

# 生成间隔（秒）
@export var spawn_interval := 1.0
# 最小生成距离（像素）
@export var spawn_distance_min := 120.0
# 最大生成距离（像素）
@export var spawn_distance_max := 300.0
# 最大蝙蝠数量
@export var max_bats := 10
# 最大尝试次数
@export var max_attempts := 10

# 生成计时器
var spawn_timer := 0.0
# 导航区域引用
@onready var navigation_region: NavigationRegion2D = get_node("/root/World/NavigationRegion2D")
# @onready var navigation_region_2d: NavigationRegion2D = $'../NavigationRegion2D'

func _physics_process(delta: float) -> void:
	# 累加时间
	spawn_timer += delta
	# 达到生成间隔时生成蝙蝠
	if spawn_timer >= spawn_interval:
		spawn_timer = 0.0
		spawn_bat()

func spawn_bat() -> void:
	# 获取玩家
	var player = get_tree().get_first_node_in_group("player")
	# 如果玩家不存在或蝙蝠数量已达上限，则不生成
	if not player or get_tree().get_nodes_in_group("bat").size() >= max_bats:
		return
	
	# 尝试多次找到有效位置
	for i in range(max_attempts):
		# 随机角度（0-2π）
		var angle = randf() * TAU
		# 随机距离
		var distance = randf_range(spawn_distance_min, spawn_distance_max)
		# 计算生成位置：玩家位置 + 极坐标转直角坐标
		var spawn_pos = player.global_position + Vector2(cos(angle), sin(angle)) * distance
		
		# 检查位置是否在导航区域内
		if is_position_valid(spawn_pos):
			# 实例化蝙蝠
			var bat = BAT_SCENE.instantiate()
			bat.global_position = spawn_pos
			bat.add_to_group("bat")
			get_parent().add_child(bat)
			return

func is_position_valid(pos: Vector2) -> bool:
	# 检查位置是否在导航多边形内
	if not navigation_region or not navigation_region.navigation_polygon:
		return true
	
	var nav_poly = navigation_region.navigation_polygon
	# 遍历导航区域中的所有多边形
	var polygons = nav_poly.get_polygon_count()
	for i in range(polygons):
		var polygon = nav_poly.get_polygon(i)  # 获取多边形的顶点索引数组
		if is_point_in_polygon(pos, polygon, nav_poly.vertices):
			# 只要在任意一个多边形内就返回true
			return true
	return false

# 多边形边界：
#     A -------- B
#     |          |
#     | • P1     |  ← P1在内部（射线穿过1次）
#     |          |
#     C -------- D
# • P2 在外部（射线穿过0次或2次）
func is_point_in_polygon(point: Vector2, polygon: PackedInt32Array, vertices: PackedVector2Array) -> bool:
	# 射线法判断点是否在多边形内
	var inside = false # 初始假设点在外部
	var j = polygon.size() - 1 # 上一个顶点索引（首尾相连）
	for i in range(polygon.size()):
		var vi = vertices[polygon[i]] # 当前顶点
		var vj = vertices[polygon[j]] # 上一个顶点
		# 判断射线是否与边 vj-vi 相交
		# 条件1: (vi.y > point.y) != (vj.y > point.y)
		#   → 边的两个端点在射线上下两侧
		# 条件2: point.x < 交点的x坐标
		#   → 交点在点的右侧
		if ((vi.y > point.y) != (vj.y > point.y)) and (point.x < (vj.x - vi.x) * (point.y - vi.y) / (vj.y - vi.y) + vi.x):
			inside = !inside
		j = i
	return inside
